package genericReflection;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

public class TypeLiterals {
    public static void main(String[] args) throws Exception {
        // ArrayList<Integer>和ArrayList<Character>都擦除到ArrayList
        // 通过TypeLiteral可以让map区分他们，从而得到他们对应的格式化函数

        var formatter = new Formatter();
        formatter.forType(
            new TypeLiteral<ArrayList<Integer>>(){},
            lst -> join(" ", lst)
        );
        formatter.forType(
            new TypeLiteral<ArrayList<Character>>(){},
            lst -> "\"" + join("", lst) + "\""
        );
        System.out.println(formatter.formatFields(new Sample()));
    }

    // 把元素合并在一起
    private static <T> String join(String separator, ArrayList<T> elements) {
        var result = new StringBuilder();
        for (T e : elements) {
            if (result.length() > 0) {
                result.append(separator);
            }
            result.append(e.toString());
        }
        return result.toString();
    }
}

class Sample {
    ArrayList<Integer> nums;
    ArrayList<Character> chars;
    ArrayList<String> strings;

    public Sample() {
        nums = new ArrayList<>();
        nums.add(42);
        nums.add(1729);

        chars = new ArrayList<>();
        chars.add('H');
        chars.add('i');

        strings = new ArrayList<>();
        strings.add("Hello");
        strings.add("World");
    }
}

class Formatter {
    private Map<TypeLiteral<?>, Function<?, String>> rules = new HashMap<>();

    public <T> void forType(TypeLiteral<T> type, Function<T, String> formatterForType) {
        rules.put(type, formatterForType);
    }

    // 找到字段的类型，并调用格式化函数
    public String formatFields(Object obj) throws IllegalArgumentException, IllegalAccessException {
        var result = new StringBuilder();

        for (var f : obj.getClass().getDeclaredFields()) {
            // 字段名称
            result.append(f.getName());
            result.append("=");
            f.setAccessible(true);

            // 获取格式化函数， 格式化字段的值
            var formatterForType = rules.get(TypeLiteral.of(f.getGenericType()));
            if (formatterForType != null) {
                @SuppressWarnings("unchecked")
                var objectFormatter = (Function<Object, String>)formatterForType;

                result.append(objectFormatter.apply(f.get(obj)));
            }
            else {
                result.append(f.get(obj).toString());
            }
            result.append("\n");
        }

        return result.toString();
    }

}

class TypeLiteral<T> {
    private Type type;

    public TypeLiteral() {
        Type parenType = getClass().getGenericSuperclass();

        // List<String>, Map<K,V>之类的类型
        if (parenType instanceof ParameterizedType paramType) {
            type = paramType.getActualTypeArguments()[0];
        }
        else {
            throw new UnsupportedOperationException("Construct as new TypeLiteral<...>(){}");
        }
    }

    public TypeLiteral(Type type) {
        this.type = type;
    }

    public static TypeLiteral<?> of(Type type) {
        return new TypeLiteral<Object>(type);
    }

    public String toString() {
        // instanceof Class 与 instanceof Class<?>等价, 但是不能用 instanceof Class<T>
        // instanceof 不考虑泛型信息
        if (type instanceof Class<?> clazz) {
            return clazz.getName();
        }
        return type.toString();
    }

    public boolean equals(Object otherObject) {
        return otherObject instanceof TypeLiteral<?> other && type.equals(other.type);
    }

    public int hashCode() {
        return type.hashCode();
    }
}
